//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010, Shane J. M. Liesegang
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright 
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright 
//       notice, this list of conditions and the following disclaimer in the 
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of any 
//       contributors may be used to endorse or promote products derived from 
//       this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.
//////////////////////////////////////////////////////////////////////////////

#pragma once

///Our base simulation element that gets inserted to the World
/** 
 * This is the base class from which most of the simulation elements in Angel
 *  derive. When you insert a Renderable into the World, it will receive 
 *  Update and Render calls once per frame. 
 */
class Renderable
{
        friend class World;

public:
        /**
         * The base constructor just sets a flag on the Renderable to not 
         *  delete it, since that would be kind of a buzzkill out of the gate. 
         * 
         * @param _deleteMe 
         */
        Renderable() : _deleteMe(false) {}
        
        /**
         * Abstract base class needs a virtual destructor. 
         */
        virtual ~Renderable() {}
        
        /**
         * This function gets called once per frame. Any game logic for an Actor
         *  should be done in this function, since it provides you with a dt for
         *  controlling rate of movement, animation, etc. 
         * 
         * @param dt The amount of time (in seconds) that has elapsed since the 
         *  last frame. 
         */
        virtual void Update(float dt) {}
        
        /**
         * This function also gets called once per frame, \b after the 
         *  Renderable::Update call. Anything you do in this function should be
         *  strictly related to drawing something on the screen. Moving it, 
         *  changing its appearance/properties/etc. should happen in Update. 
         */
        virtual void Render() {}
        
        /**
         * A safe way to kill off a Renderable -- it will be removed from the 
         *  world and deleted from memory at the end of the current Update loop. 
         * 
         * The protected Renderable::PreDestroy function is guaranteed to be 
         *  called exactly once by this function, even if you call it many times. 
         */
        void Destroy() 
        {
                if( IsDestroyed() )
                        return;
                PreDestroy(); 
                _deleteMe = true;
        }
        
        /**
         * Used by the World to see if a Renderable is flagged to be deleted. 
         * 
         * @return True if the Renderable should be removed and deleted. 
         */
        bool IsDestroyed() {return _deleteMe;}
        
        /**
         * The layer to which this Renderable has been assigned in the world. 
         *  returns garbage if it hasn't been added to the World yet. (Negative 
         *  layers are valid.)
         * 
         * @return The world layer for this Renderable
         */
        int GetLayer() {return _layer;}
protected:
        /**
         * Will get called before this Renderable is destroyed (if you do it via 
         *  the Destroy function, obviously). Override this function in a subclass
         *  to do any cleanup work that is appropriate to your element. 
         */
        virtual void PreDestroy() {}

protected:
        bool _deleteMe;
        int _layer;
};
